#pragma once

#include <atomic>
#include <fstream>
#include <iostream>
#include <string>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
namespace Tool
{
  const std::string basic_path = "./TempFiles/";

  class PathBuilder
  {
  public:
    static std::string addSuffix(const std::string &file_name, std::string suffix)
    {
      std::string path = basic_path + file_name + suffix;
      return path;
    }

  public:
    static std::string buildStdInPath(const std::string &file_name)
    {
      return addSuffix(file_name, ".stdin");
    }
    static std::string buildStdOutPath(const std::string &file_name)
    {
      return addSuffix(file_name, ".stdout");
    }
    static std::string buildStdErrPath(const std::string &file_name)
    {
      return addSuffix(file_name, ".stderr");
    }
    static std::string buildSourcePath(const std::string &file_name)
    {
      return addSuffix(file_name, ".cpp");
    }

    static std::string buildExecutablePath(const std::string &file_name)
    {
      return addSuffix(file_name, ".exe");
    }

    static std::string buildCompileErrorPath(const std::string &file_name)
    {
      return addSuffix(file_name, ".compile_err");
    }

    static std::string buildErrorPath(const std::string &file_name)
    {
      return addSuffix(file_name, ".err");
    }
  };

  class FileHandler
  {
  public:
    static bool isFileExist(const std::string &file_path)
    {
      struct stat st;
      if (stat(file_path.c_str(), &st) == 0)
      {
        // 获取属性成功，文件已经存在
        return true;
      }

      return false;
    }

    static std::string creatUniqueFileName()
    {
      struct timeval _time;
      gettimeofday(&_time, nullptr);
      std::string time_str = std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);

      static std::atomic<int> file_index(0);
      std::string file_name = "temp_" + time_str + "_" + std::to_string(file_index.fetch_add(1));

      return file_name;
    }

    static bool writeFile(const std::string &file_path, const std::string &content)
    {
      std::ofstream out(file_path);
      if (!out.is_open())
      {
        return false;
      }
      out.write(content.c_str(), content.size());
      out.close();
      return true;
    }

    static bool readFile(const std::string &file_path, std::string &content, bool keep_flag = false)
    {
      content.clear();

      std::ifstream in(file_path);
      if (!in.is_open())
      {
        return false;
      }
      std::string line;
      // getline:不保存行分割符,有些时候需要保留\n,
      // getline内部重载了强制类型转化
      while (std::getline(in, line))
      {
        content += line;
        content += (keep_flag ? "\n" : "");
      }
      in.close();
      return true;
    }

    static void removeFile(const std::string &filename)
    {
      const std::string str_compile_err = PathBuilder::buildCompileErrorPath(filename);
      if (!str_compile_err.empty())
        unlink(str_compile_err.c_str());
      const std::string str_stderr = PathBuilder::buildStdErrPath(filename);
      if (!str_stderr.empty())
        unlink(str_stderr.c_str());
      const std::string str_stdin = PathBuilder::buildStdInPath(filename);
      if (!str_stdin.empty())
        unlink(str_stdin.c_str());
      const std::string str_stdout = PathBuilder::buildStdOutPath(filename);
      if (!str_stdout.empty())
        unlink(str_stdout.c_str());
      const std::string str_source = PathBuilder::buildSourcePath(filename);
      if (!str_source.empty())
        unlink(str_source.c_str());
      const std::string std_exectue = PathBuilder::buildExecutablePath(filename);
      if (!std_exectue.empty())
        unlink(std_exectue.c_str());
    }
  };

  class StrHelper
  {
  public:
    // 静态成员函数，用于分割字符串
    // 参数：待分割的字符串str，分隔符sep，存储结果的向量result
    // 返回值：分割后的子字符串数量
    static size_t split(const std::string &str, const std::string &sep, std::vector<std::string> &result)
    {
      int pos = 0; // 用于记录分隔符在字符串中的位置
      int idx = 0; // 用于遍历字符串的索引

      // 遍历字符串，直到索引超出字符串长度
      while (idx < str.size())
      {
        // 从当前索引开始查找分隔符，返回分隔符的起始位置
        pos = str.find(sep, idx);

        // 如果未找到分隔符，说明已经到达字符串末尾或分隔符不在剩余部分
        if (pos == std::string::npos)
        {
          // 将剩余部分作为最后一个子字符串添加到结果向量中
          std::string tmp = str.substr(idx);
          result.push_back(tmp);
          // 返回结果向量的大小，即子字符串的数量
          return result.size();
        }

        // 如果分隔符的起始位置与当前索引相同，说明两个分隔符之间没有数据
        if (pos == idx)
        {
          // 更新索引，跳过这个分隔符
          idx = pos + sep.size();
          continue;
        }

        // 提取两个分隔符之间的子字符串，并添加到结果向量中
        std::string tmp = str.substr(idx, pos - idx);
        result.push_back(tmp);
        // 更新索引，跳过这个分隔符和已经处理的子字符串
        idx = pos + sep.size();
      }
      // 返回结果向量的大小，即子字符串的数量
      return result.size();
    }
  };
}